﻿

using Microsoft.Maps.MapControl.Core;
using System.Collections.Generic;
using Microsoft.Maps.MapControl;
using System.Windows;
using System.Windows.Controls;
using MyFloridaHouse.SharpMap.Converters.WellKnownText;
using MyFloridaHouse.libSvBingMapsMultiShape;
using MyFloridaHouse.SharpMap.Geometries;
using System;
using MyFloridaHouse.ServiceConn.DistrBldrSvcRef;
using System.Collections.ObjectModel;

namespace MyFloridaHouse.libSvOpenDistricts.MapShapes
{

    public static class MapShapeTools
    {

        public static MultiMapShapeBase BuildShape(MapMultiShapeDTO mapMultiShapeDTO)
        {
            MultiMapShapeBase mapShape = null;

            if (mapMultiShapeDTO.shapeType == MapMultiShapeType.Point)
            {
                // ignore any points, just use the centerpoint.
                mapShape = null;
            }

            else if (mapMultiShapeDTO.shapeType == MapMultiShapeType.Polygon)
            {
                MapMultiPolygon newShape = new MapMultiPolygon();
                newShape.Vertices = GetMultiShapeLocationCollection(mapMultiShapeDTO);
                mapShape = newShape;
            }
            else if (mapMultiShapeDTO.shapeType == MapMultiShapeType.MultiPolygon)
            {
                MapMultiPolygon newShape = new MapMultiPolygon();
                newShape.Vertices = GetMultiShapeLocationCollection(mapMultiShapeDTO);
                mapShape = newShape;
            }
            else if (mapMultiShapeDTO.shapeType == MapMultiShapeType.LineString)
            {
                MapMultiPolyline newShape = new MapMultiPolyline();
                newShape.Vertices = GetMultiShapeLocationCollection(mapMultiShapeDTO);
                mapShape = newShape;
            }
            else if (mapMultiShapeDTO.shapeType == MapMultiShapeType.MultiLineString)
            {
                MapMultiPolyline newShape = new MapMultiPolyline();
                newShape.Vertices = GetMultiShapeLocationCollection(mapMultiShapeDTO);
                mapShape = newShape;
            }
            else if (mapMultiShapeDTO.shapeType == MapMultiShapeType.GeometricCollection)
            {
                MapMultiGeometry mapGeometry = new MapMultiGeometry();
                List<LocationCollection> points = new List<LocationCollection>();
            }
            else
            {
                // ignore it
            }
            return mapShape;
        }

        private static IList<LocationCollection> GetMultiShapeLocationCollection(MapMultiShapeDTO multiShape)
        {
            List<LocationCollection> points = new List<LocationCollection>();
            foreach (var shape in multiShape.shapeList)
            {
                points.Add(ConvertPointDTOListToLocationCollection(shape.ExteriorRing));
                foreach (var interiorRing in shape.InteriorRings)
                {
                    points.Add(ConvertPointDTOListToLocationCollection(interiorRing));
                }
            }
            return points;
        }

        private static LocationCollection ConvertPointDTOListToLocationCollection(ObservableCollection<PointDTO> verticies)
        {

            LocationCollection locs = new LocationCollection();
            foreach (var vert in verticies)
            {
                Location mapLoc = new Location(vert.latitude, vert.longitude);
                locs.Add(mapLoc);
            }

            return locs;
        }













        // Build shapes takes a well known text string (WKT) 
        // 1. breaks it into separate shapes
        // 2. converts each shape to a Bing maps shape
        // 3. puts the bing map shape object into a list
        // 4. returns the list
        public static MultiMapShapeBase BuildShape(string geomText)
        {
            MultiMapShapeBase mapShape = null;
            if (geomText != null)
            {
                if (geomText.Length > 0)
                {
                    mapShape = ExtractShapePoints(geomText);

                }
            }
            return mapShape;
        }

        private static MultiMapShapeBase ExtractShapePoints(string geomText)
        {
            MultiMapShapeBase mapShape = null;

            SharpMap.Geometries.Geometry gm = GeometryFromWKT.Parse(geomText);

            if (gm is Polygon)
            {
                MapMultiPolygon mapPoly = new MapMultiPolygon();
                mapPoly.Vertices = GetPolygonPoints((SharpMap.Geometries.Polygon)gm);
                mapShape = mapPoly;
            }
            else if (gm is MultiPolygon)
            {
                MapMultiPolygon mapMPoly = new MapMultiPolygon();
                mapMPoly.Vertices = GetMultiPolygonPoints((SharpMap.Geometries.MultiPolygon)gm);
                mapShape = mapMPoly;
            }
            else if (gm is LineString)
            {
                MapMultiPolyline mapLine = new MapMultiPolyline();
                mapLine.Vertices = GetPolylinePoints((SharpMap.Geometries.LineString)gm);
                mapShape = mapLine;
            }
            else if (gm is MultiLineString)
            {
                MapMultiPolyline mapMLine = new MapMultiPolyline();
                mapMLine.Vertices = GetMultiPolylinePoints((SharpMap.Geometries.MultiLineString)gm);
                mapShape = mapMLine;
            }
            else if (gm is SharpMap.Geometries.Point)
            {
                // ignore any points, just use the centerpoint.
                mapShape = null;

            }
            else if (gm is SharpMap.Geometries.GeometryCollection)
            {
                MapMultiGeometry mapGeometry = new MapMultiGeometry();
                List<LocationCollection> points = new List<LocationCollection>();

                SharpMap.Geometries.GeometryCollection smCollection = (SharpMap.Geometries.GeometryCollection)gm;
                foreach (var smItem in smCollection.Collection)
                {
                    //todo: need to parse each item in the geometrycollection into a single MultiShape object, but that wasn't defined in blog
                    // need to grab any lines, polylines, polygons, multipolyline,multipolygon,points and convert to all 1 set of points
                    // I think multiMapShape doesn't care, it treats them all as line segments anyway
                    // for now, just grab 1 piece
                    if (smItem is SharpMap.Geometries.Polygon)
                    {

                        mapGeometry.AddPolygonVertices(GetPolygonPoints((SharpMap.Geometries.Polygon)smItem));
                    }
                    else if (smItem is SharpMap.Geometries.MultiPolygon)
                    {
                        mapGeometry.AddPolygonVertices(GetMultiPolygonPoints((SharpMap.Geometries.MultiPolygon)smItem));
                    }
                    else if (smItem is SharpMap.Geometries.LineString)
                    {
                        mapGeometry.AddPolylineVertices(GetPolylinePoints((SharpMap.Geometries.LineString)smItem));
                    }
                    else if (smItem is SharpMap.Geometries.LineString)
                    {
                        mapGeometry.AddPolylineVertices(GetMultiPolylinePoints((SharpMap.Geometries.MultiLineString)smItem));
                    }
                    else if (smItem is SharpMap.Geometries.Point)
                    {
                        //todo: log this message instead of displaying to user
                        //MessageBox.Show("Layer [" + rgn.layer.layerID.ToString() + "Region [" + regionID + "] has  geometry collection part of Point in it");
                        MessageBox.Show("Can't create shape from Geometry text from [" + geomText + "]");
                    }
                    else
                    {
                        //todo: log this message instead of displaying to user
                        //MessageBox.Show("Layer [" + rgn.layer.layerID.ToString() + "Region [" + regionID + "] has  geometry collection part of unkown type [" + gm.ToString() + "] in it");
                        MessageBox.Show("Can't create shape from Geometry text from [" + geomText + "]");
                    }

                }
                mapShape = mapGeometry;
            }

            else
            {
                // error
                //todo: write invalid shape rgn.regionID.ToString() to log file
                MessageBox.Show("Can't create shape from Geometry text from [" + geomText + "]");

            }

            return mapShape;

        }

        private static List<LocationCollection> GetPolygonPoints(SharpMap.Geometries.Polygon smPoly)
        {
            List<LocationCollection> points = new List<LocationCollection>();
            points.Add(ConvertPointsToLocationCollection(smPoly.ExteriorRing.Vertices));
            foreach (var interiorRing in smPoly.InteriorRings)
            {
                points.Add(ConvertPointsToLocationCollection(interiorRing.Vertices));
            }
            return points;
        }

        private static List<LocationCollection> GetMultiPolygonPoints(SharpMap.Geometries.MultiPolygon smMultiPoly)
        {
            List<LocationCollection> points = new List<LocationCollection>();
            foreach (var smPoly in smMultiPoly.Polygons)
            {
                points.AddRange(GetPolygonPoints(smPoly));
            }
            return points;
        }

        private static List<LocationCollection> GetPolylinePoints(SharpMap.Geometries.LineString smLine)
        {
            List<LocationCollection> points = new List<LocationCollection>();
            points.Add(ConvertPointsToLocationCollection(smLine.Vertices));
            return points;
        }

        private static List<LocationCollection> GetMultiPolylinePoints(SharpMap.Geometries.MultiLineString smMultiLine)
        {
            List<LocationCollection> points = new List<LocationCollection>();
            foreach (var smLine in smMultiLine.LineStrings)
            {
                points.AddRange(GetPolylinePoints(smLine));
            }
            return points;
        }



        private static LocationCollection ConvertPointsToLocationCollection(List<SharpMap.Geometries.Point> verticies)
        {

            LocationCollection locs = new LocationCollection();
            foreach (var vert in verticies)
            {
                Location mapLoc = new Location(vert.Y, vert.X);
                locs.Add(mapLoc);
            }

            return locs;
        }


    }
}
